package com.mixed.mixedserver.game.network;

import com.mixed.mixedserver.game.entity.GameMessage;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@Component
public class GameServerHandler extends SimpleChannelInboundHandler<GameMessage> {
    private static final Logger logger = LoggerFactory.getLogger(GameServerHandler.class);
    
    // 存储所有连接的玩家
    private final ConcurrentHashMap<String, ChannelHandlerContext> players = new ConcurrentHashMap<>();
    private final ConcurrentHashMap<ChannelHandlerContext, String> channelToPlayer = new ConcurrentHashMap<>();
    private final AtomicInteger playerIdCounter = new AtomicInteger(0);
    
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        logger.info("New client connected: {}", ctx.channel().remoteAddress());
        super.channelActive(ctx);
    }
    
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        String playerId = channelToPlayer.remove(ctx);
        if (playerId != null) {
            players.remove(playerId);
            logger.info("Player {} disconnected", playerId);
            
            // 广播玩家离开消息
            GameMessage leaveMessage = new GameMessage(
                GameMessage.MessageType.PLAYER_LEAVE, 
                playerId, 
                null
            );
            broadcastToAll(leaveMessage, ctx);
        }
        super.channelInactive(ctx);
    }
    
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, GameMessage msg) throws Exception {
        logger.debug("Received message: type={}, playerId={}", msg.getType(), msg.getPlayerId());
        
        switch (msg.getType()) {
            case CONNECT:
                handleConnect(ctx, msg);
                break;
            case HEARTBEAT:
                handleHeartbeat(ctx, msg);
                break;
            case PLAYER_MOVE:
                handlePlayerMove(ctx, msg);
                break;
            case PLAYER_ROTATE:
                handlePlayerRotate(ctx, msg);
                break;
            case PLAYER_ACTION:
                handlePlayerAction(ctx, msg);
                break;
            case CHAT_MESSAGE:
                handleChatMessage(ctx, msg);
                break;
            default:
                logger.warn("Unknown message type: {}", msg.getType());
        }
    }
    
    private void handleConnect(ChannelHandlerContext ctx, GameMessage msg) {
        String playerId = "player_" + playerIdCounter.incrementAndGet();
        players.put(playerId, ctx);
        channelToPlayer.put(ctx, playerId);
        
        logger.info("Player {} joined the game", playerId);
        
        // 发送连接确认
        GameMessage response = new GameMessage(
            GameMessage.MessageType.PLAYER_JOIN,
            playerId,
            new GameMessage.PlayerData()
        );
        ctx.writeAndFlush(response);
        
        // 广播新玩家加入
        broadcastToAll(response, ctx);
    }
    
    private void handleHeartbeat(ChannelHandlerContext ctx, GameMessage msg) {
        // 回复心跳
        GameMessage heartbeatResponse = new GameMessage(
            GameMessage.MessageType.HEARTBEAT,
            msg.getPlayerId(),
            null
        );
        ctx.writeAndFlush(heartbeatResponse);
    }
    
    private void handlePlayerMove(ChannelHandlerContext ctx, GameMessage msg) {
        // 验证玩家ID
        String playerId = channelToPlayer.get(ctx);
        if (playerId == null || !playerId.equals(msg.getPlayerId())) {
            logger.warn("Invalid player ID in move message: {}", msg.getPlayerId());
            return;
        }
        
        // 广播玩家移动
        broadcastToAll(msg, ctx);
    }
    
    private void handlePlayerRotate(ChannelHandlerContext ctx, GameMessage msg) {
        // 验证玩家ID
        String playerId = channelToPlayer.get(ctx);
        if (playerId == null || !playerId.equals(msg.getPlayerId())) {
            logger.warn("Invalid player ID in rotate message: {}", msg.getPlayerId());
            return;
        }
        
        // 广播玩家旋转
        broadcastToAll(msg, ctx);
    }
    
    private void handlePlayerAction(ChannelHandlerContext ctx, GameMessage msg) {
        // 验证玩家ID
        String playerId = channelToPlayer.get(ctx);
        if (playerId == null || !playerId.equals(msg.getPlayerId())) {
            logger.warn("Invalid player ID in action message: {}", msg.getPlayerId());
            return;
        }
        
        // 广播玩家动作
        broadcastToAll(msg, ctx);
    }
    
    private void handleChatMessage(ChannelHandlerContext ctx, GameMessage msg) {
        // 验证玩家ID
        String playerId = channelToPlayer.get(ctx);
        if (playerId == null || !playerId.equals(msg.getPlayerId())) {
            logger.warn("Invalid player ID in chat message: {}", msg.getPlayerId());
            return;
        }
        
        // 广播聊天消息
        broadcastToAll(msg, null);
    }
    
    private void broadcastToAll(GameMessage message, ChannelHandlerContext excludeCtx) {
        players.values().forEach(ctx -> {
            if (ctx != excludeCtx && ctx.channel().isActive()) {
                ctx.writeAndFlush(message);
            }
        });
    }
    
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                logger.warn("Client {} read timeout, closing connection", ctx.channel().remoteAddress());
                ctx.close();
            }
        }
        super.userEventTriggered(ctx, evt);
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        logger.error("Handler exception for client {}", ctx.channel().remoteAddress(), cause);
        ctx.close();
    }
    
    // 获取在线玩家数量
    public int getOnlinePlayerCount() {
        return players.size();
    }
    
    // 获取所有在线玩家ID
    public String[] getOnlinePlayerIds() {
        return players.keySet().toArray(new String[0]);
    }
}